﻿

using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using System;
using System.Configuration;
using System.Reflection;
using System.Text;

namespace RM.BasicLibrary.Logs
{
    public interface IBaseLog
    {
        void Error(string message, Exception ex);
        void Debug(string message);
        void Info(string message);
        void Warn(string message);
    }
    public abstract class BaseLog : IBaseLog
    {
        protected string repositoryName = "LocalLog";
        public abstract void SetLocalLog(string logPath, string fileName = "yyyy-MM-dd'.html'", string log_pattern = "<hr color=red />%date %level %c- %m%n <hr/>", string repositoryName = "LocalLog");
#if NET45 || NET46
        public abstract void SetDBLog(string connectionString, string commandText, DBType dBType = DBType.MSSQL, string repositoryName = "LocalLog");
#endif
        private string MessageFormat(string message)
        {
            return Root.Ins.CodeInfo.GetCodeInfo(3, true, message).ToString();
        }
        private Type LogName()
        {
            System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(2, true);
            return st.GetFrame(0).GetMethod().DeclaringType;
        }
        public void Debug(string message)
        {
            ILog log = LogManager.GetLogger(repositoryName, LogName());
            log.Debug(MessageFormat(message));
        }

        public void Error(string message, Exception ex)
        {
            ILog log = LogManager.GetLogger(repositoryName, LogName());
            log.Error(MessageFormat(message), ex);
        }

        public void Info(string message)
        {
            ILog log = LogManager.GetLogger(repositoryName, LogName());
            log.Info(MessageFormat(message));
        }

        public void Warn(string message)
        {
            ILog log = LogManager.GetLogger(repositoryName, LogName());
            log.Warn(MessageFormat(message));
        }
    }
    public class LogNet : BaseLog
    {
        const string LocalRepositoryName = "LocalLog";
        const string DBRepositoryName = "DBLog";
        public LogConfig logConfig = new LogConfig();
        public LogNet()
        {
            repositoryName = LocalRepositoryName;
            logConfig.repositoryName = LocalRepositoryName;
            logConfig.LocalConfig();
        }
#if NET45 || NET46
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="commandText"></param>
        /// <param name="dBType"></param>
        /// <param name="repositoryName"></param>
        public override void SetDBLog(string connectionString, string commandText, DBType dBType = DBType.MSSQL, string repositoryName = "DBLog")
        {
            logConfig.ConnectionString = connectionString;
            base.repositoryName = DBRepositoryName;
            logConfig.repositoryName = DBRepositoryName;
            logConfig.CmdText = commandText;
            if (dBType == DBType.MSSQL)
                logConfig.ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            else if (dBType == DBType.MYSQL)
                logConfig.ConnectionType = "MySql.Data.MySqlClient.MySqlConnection, MySql.Data";
            logConfig.DataBaseConfig();
        }
#endif
        /// <summary>
        /// 
        /// </summary>
        /// <param name="logPath"></param>
        /// <param name="fileName"></param>
        /// <param name="log_pattern"></param>
        /// <param name="repositoryName"></param>
        public override void SetLocalLog(string logPath, string fileName = "yyyy-MM-dd'.html'", string log_pattern = "<hr color=red />%date %level %c- %m%n <hr/>", string repositoryName = "LocalLog")
        {
            base.repositoryName = LocalRepositoryName;
            logConfig.repositoryName = LocalRepositoryName;
            logConfig.Log_Pattern = log_pattern;
            logConfig.FileName = fileName;
            logConfig.LogPath = logPath;
            logConfig.LocalConfig();
        }
    }
    public class LogConfig
    {
        internal string repositoryName = string.Empty;
        internal string Log_Pattern = $"<hr color=red />%date %level %c- %m%n <hr/>";
        internal string FileName = "yyyy-MM-dd'.html'";
        internal string LogPath = "Log/";
        internal string ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
        internal string CmdText = @"INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)";
        internal string ConnectionString = string.Empty;
        /// <summary>
        /// 本地日志设置
        /// </summary>
        public void LocalConfig()
        {

            Hierarchy hierarchy = null;
            try
            {
                hierarchy = (Hierarchy)LogManager.GetRepository(repositoryName);
            }
            catch (Exception)
            {
            }
            if (hierarchy == null)
                try
                {
                    hierarchy = (Hierarchy)LogManager.CreateRepository(repositoryName);
                }
                catch (Exception)
                {
                }
            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = Log_Pattern;
            patternLayout.ActivateOptions();

            // 控制台输出的日志
            TraceAppender tracer = new TraceAppender();
            tracer.Layout = patternLayout;
            tracer.ActivateOptions();
            hierarchy.Root.AddAppender(tracer);

            // 滚动文件日志
            RollingFileAppender roller = new RollingFileAppender();
            roller.Layout = patternLayout;
            roller.AppendToFile = true;
            roller.RollingStyle = RollingFileAppender.RollingMode.Date;
            roller.MaxSizeRollBackups = 4;
            roller.MaximumFileSize = "1MB";
            roller.StaticLogFileName = false;
            roller.File = LogPath;
            roller.DatePattern = FileName;
            roller.Encoding = Encoding.UTF8;
            roller.ActivateOptions();
            hierarchy.Root.AddAppender(roller);
            hierarchy.Root.Level = Level.All;
            hierarchy.Configured = true;

            BasicConfigurator.Configure(hierarchy, roller);
            LogManager.GetLogger(repositoryName, MethodBase.GetCurrentMethod().DeclaringType).Info("本地日志启动");
        }
#if NET45 || NET46
        /// <summary>
        /// 数据库日志设置
        /// </summary>
        public void DataBaseConfig()
        {

            Hierarchy hierarchy = null;
            Root.BasicIns.ExFilter.Execute(() => hierarchy = (Hierarchy)LogManager.GetRepository(repositoryName));
            if (hierarchy == null)
                Root.BasicIns.ExFilter.Execute(() => hierarchy = (Hierarchy)LogManager.CreateRepository(repositoryName));
            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = Log_Pattern;
            patternLayout.ActivateOptions();

            TraceAppender tracer = new TraceAppender();
            tracer.Layout = patternLayout;
            tracer.ActivateOptions();
            hierarchy.Root.AddAppender(tracer);

            // ado.net数据库日志
            AdoNetAppender appender = new AdoNetAppender();
            appender.Name = "adoNetAppender";

            appender.ConnectionType = ConnectionType;
            appender.ConnectionString = ConnectionString;
            appender.CommandText = CmdText;
            appender.CommandType = System.Data.CommandType.Text;
            appender.BufferSize = 1;

            AdoNetAppenderParameter parameter = new AdoNetAppenderParameter();
            parameter.DbType = System.Data.DbType.Date;
            parameter.ParameterName = "@log_date";
            parameter.Size = 255;
            parameter.Layout = new RawTimeStampLayout();
            appender.AddParameter(parameter);

            parameter = new AdoNetAppenderParameter();
            parameter.DbType = System.Data.DbType.String;
            parameter.ParameterName = "@thread";
            parameter.Size = 50;
            patternLayout = new PatternLayout("%thread");
            parameter.Layout = new Layout2RawLayoutAdapter(patternLayout);
            appender.AddParameter(parameter);

            parameter = new AdoNetAppenderParameter();
            parameter.DbType = System.Data.DbType.String;
            parameter.Size = 50;
            parameter.ParameterName = "@log_level";
            patternLayout = new PatternLayout("%level");
            parameter.Layout = new Layout2RawLayoutAdapter(patternLayout);
            appender.AddParameter(parameter);

            parameter = new AdoNetAppenderParameter();
            parameter.DbType = System.Data.DbType.String;
            parameter.ParameterName = "@logger";
            parameter.Size = 255;
            patternLayout = new PatternLayout("%logger");
            parameter.Layout = new Layout2RawLayoutAdapter(patternLayout);
            appender.AddParameter(parameter);

            parameter = new AdoNetAppenderParameter();
            parameter.DbType = System.Data.DbType.String;
            parameter.ParameterName = "@message";
            parameter.Size = 4000;
            patternLayout = new PatternLayout("%message");
            parameter.Layout = new Layout2RawLayoutAdapter(patternLayout);
            appender.AddParameter(parameter);

            parameter = new AdoNetAppenderParameter();
            parameter.DbType = System.Data.DbType.String;
            parameter.ParameterName = "@exception";
            parameter.Size = 2000;
            parameter.Layout = new Layout2RawLayoutAdapter(new ExceptionLayout());
            appender.AddParameter(parameter);

            appender.ActivateOptions();
            hierarchy.Root.AddAppender(appender);

            hierarchy.Root.Level = Level.All;
            hierarchy.Configured = true;

            BasicConfigurator.Configure(appender);
            LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType).Info("数据库日志启动");
        }
#endif
    }

}
